home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-05
/
netbtime.zip
/
TIMESEND.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-03-09
|
25KB
|
518 lines
TITLE TIMESEND
PAGE 65,132
;╔═══════════════════════════════════════════════════════════════════════════╗
;║ TIMESEND -- A TSR to Broadcast Time Periodically Via NETBIOS ║
;║ ║
;║ I am the original author of this work and hereby place it into ║
;║ the public domain. If your conscience bothers you, please feel ║
;║ free to send me $25.00 so that I may provide more such goodies. ║
;║ ║
;║ NOTE: This source code was written to be assembled with OPTASM. ║
;║ Phase errors and near jump problems will surely occur if ║
;║ MASM is used. Also, this program must be constructed as ║
;║ a .COM file. ║
;║ ║
;║ Programmer ...... George W. Mays ║
;║ Date ............ February, 1993 ║
;║ Site ............ 3314 Prince George ║
;║ San Antonio, TX 78230 ║
;║ Source .......... 80286 Assembler ║
;║ System .......... IBM PC/AT Compatible System Under MSDOS ║
;║ ║
;╚═══════════════════════════════════════════════════════════════════════════╝
.286
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
INCLUDE NETBIOS.INC
ORG 100H ;SKIP TO END OF THE PSP
ENTPT: JMP INITIALIZE ;COM FILE ENTRY ALWAYS AT 100H
COPYRIGHT DB "TIMESEND V1.0, (C) 1993, G.W. Mays",0Ah,0Dh
DB "In the Public Domain. Use Freely.",0Ah,0Dh,'$'
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Program data area. Buffers & Stack at end of resident code. │
;╘═══════════════════════════════════════════════════════════════════════════╛
;
; Data Stuff
STACKSIZE EQU 0200h ;Our stack size
VER DW 0 ;DOS version as returned
DOSMAJOR DB 0 ;DOS major version number
DOSMINOR DB 0 ;DOS minor version number
REDIRACTIVE DB 0 ;Redirector flag
BUSYFLAG DB 0 ;NB request outstanding flag
LASTSTATUS DB 0 ;Completion code from last send
NAMENUM DB 0 ;Name Number returned by NB
SAVE_SP DW 0 ;Stack save cells
SAVE_SS DW 0
BUFF DB " " ;Data buff for NB send
PREVGUY DD 0 ;Addr of original 1C Handler
COUNTER DW 0 ;Tick counter
NTICKS DW 182 ;Tick count to trip action
MYNAME DB "TIMESERVER " ;My NETBIOS name
THEIRNAME DB "TIMECLIENT " ;Their NETBIOS name
CB NCB <> ;Our NCB
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Control is passed here by DOS via INT 0x1C (the Timer interrupt). │
;╘═══════════════════════════════════════════════════════════════════════════╛
INT_1C PROC FAR
NOP ; INT 3 ;Debug or NOP
PUSHF ;Save flags
PUSH DS
PUSH AX
; Bump & Test Counter
MOV AX,CS ;Set up addressing
MOV DS,AX
MOV AX,COUNTER ;Bump counter
INC AX
MOV COUNTER,AX
CMP AX,NTICKS ;Have we hit "NTICKS"?
JB RESTORE ;No, restore & return
XOR AX,AX ;Yes, fall thru...
MOV COUNTER,AX ;Zero counter
; Time to Broadcast Date/Time
INT 3 ;Debug or NOP
CLI ;Set our stack
MOV CS:SAVE_SP,SP ;Save stack address
MOV SP,SS ;
MOV CS:SAVE_SS,SP
MOV SP,CS
MOV SS,SP
MOV SP,OFFSET STACKTOP ;
STI
PUSHF
PUSH ES ;Save registers
PUSH DS
PUSH DI
PUSH SI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
; The Reason We Came ----------------------------
CALL DOTIME ;Get & send date & time
; -----------------------------------------------
POP AX
POP BX ;Restore registers
POP CX
POP DX
POP SI
POP DI
POP DS
POP ES
POPF
CLI
MOV SP,CS:SAVE_SS ;Restore stack address
MOV SS,SP
MOV SP,CS:SAVE_SP
STI
RESTORE:
POP AX ;Restore registers
POP DS
POPF ;Restore flags and
JMP CS:[PREVGUY] ; percolate the call
INT_1C ENDP
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Get date & time from BIOS; pack 'em up & ship 'em out.... │
;╘═══════════════════════════════════════════════════════════════════════════╛
DOTIME PROC NEAR
MOV AL,BUSYFLAG ;Test for request already
OR AL,AL ; in progress....
JZ NOTBUSY
RET ;Just skip this time thru
NOTBUSY:
MOV BUFF+00h,'D' ;Format our packet
MOV BUFF+01h,'/' ;It starts with "D/T"
MOV BUFF+02h,'T'
MOV BUFF+03h,00h
MOV AH,04h ;Get date
INT 1Ah ;From the BIOS (AT or PS/2)
MOV AX,CX ;Start forming checksum
ADD AX,DX
MOV BUFF+04h,CH ;Century (in packed decimal)
MOV BUFF+05h,CL ;Year
MOV BUFF+06h,DH ;Month
MOV BUFF+07h,DL ;Day
PUSH AX ;Save checksum accumulator
MOV AH,02h ;Get time
INT 1Ah ;From the BIOS (AT or PS/2)
POP AX ;Restore the checksum
ADD AX,CX ;Continue checksumming
ADD AX,DX
MOV BUFF+08h,CH ;Hour
MOV BUFF+09h,CL ;Minutes
MOV BUFF+0Ah,DH ;Seconds
MOV BUFF+0Bh,DL ;Daylight Savings Flag
MOV BUFF+0Ch,00h
MOV BUFF+0Dh,AL ;Store the checksum
MOV BUFF+0Eh,AH ;
MOV BUFF+0Fh,00h ;
;
CALL CLEARNCB ;Prepare NCB
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV DI,OFFSET CB.NCB_CALLNAME
MOV SI,OFFSET THEIRNAME ;Call Name
MOV CX,16
CLD
REP MOVSB
MOV AH,NAMENUM ;Name Number
MOV CB.NCB_NUM,AH
MOV CB.NCB_LENGTH,16 ;Length
MOV AX,CS
MOV ES,AX
MOV CB.NCB_BUFF_SEG,AX ;Buffer Address and
MOV CB.NCB_POST_SEG,AX ; Post Address
MOV AX,OFFSET BUFF
MOV CB.NCB_BUFF_OFF,AX
MOV AX,OFFSET NBPOST
MOV CB.NCB_POST_OFF,AX
;Function Code
MOV AL,SENDDATAGRAM+NCB_NOWAIT
MOV CB.NCB_COMMAND,AL
MOV BUSYFLAG,AL ;Set BUSYFLAG
MOV BX,OFFSET CB ;ES:BX -> NCB
CALL CALLNB ;Call NETBIOS
RET ;Return
DOTIME ENDP
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ NBPOST Function --- NETBIOS posts us here upon SEND DATAGRAM completion. │
;╘═══════════════════════════════════════════════════════════════════════════╛
NBPOST PROC NEAR
PUSHF
PUSH DS ;Save regs
PUSH AX
STI ;Reenable interrupts
NOP ; INT 3 ;Debug or NOP
MOV AX,CS ;Set DS = CS
MOV DS,AX
MOV AL,CB.NCB_RETCODE ;Tuck away completion status
MOV LASTSTATUS,AL
MOV BUSYFLAG,00h ;Clear BUSYFLAG
POP AX ;Restore regs
POP DS
POPF
IRET ;Return from interrupt
NBPOST ENDP
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ CLEARNCB Function --- Fill the NCB with binary zeroes. │
;╘═══════════════════════════════════════════════════════════════════════════╛
CLEARNCB PROC NEAR
PUSHF ;Save regs & flags
PUSH ES
PUSH DI
PUSH CX
PUSH AX
MOV AX,CS
MOV ES,AX
MOV DI,OFFSET CB ;Zero the NCB
MOV CX,NCB_SIZE
XOR AL,AL
CLD
REP STOSB
POP AX ;Restore regs & flags
POP CX
POP DI
POP ES
POPF
RET
CLEARNCB ENDP
;╔═══════════════════════════════════════════════════════════════════════════╗
;║ CALL NETBIOS - This routine is called to send an NCB to the NETBIOS. ║
;║ If a redirector is loaded use int 2Ah otherwise use int 5Ch. ║
;║ ║
;║ On entry: ║
;║ ES:BX addr of NCB ║
;║ On exit: ║
;║ AX return code ║
;╚═══════════════════════════════════════════════════════════════════════════╝
CALLNB PROC NEAR
CMP REDIRACTIVE,0 ;Is a redirector active?
JNE THRUREDIR
INT 5Ch
RET
THRUREDIR:
MOV AX,0400h
INT 2Ah
RET
CALLNB ENDP
;╞═══════════════════════════════════════════════════════════════════════════╡
PC = $ ;End of Code, OFFSET -> PC
STACKBOT = PC ;Stack starts after I/O Buffs
PC = PC + STACKSIZE ; and is STACKSIZE bytes long
STACKTOP = PC ;STACKTOP here since stack
; grows downward
PC = PC + 16
LASTBYTE = PC ;LASTBYTE in resident code
;╔═══════════════════════════════════════════════════════════════════════════╗
;║ Initialization Procedure ║
;╚═══════════════════════════════════════════════════════════════════════════╝
INITIALIZE PROC NEAR
ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;Set by loader.
NOP ; INT 3 ;Debug or NOP
MOV AX,CS
MOV DS,AX
MOV AH,9
MOV DX,OFFSET COPYRIGHT
INT 21H
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Check to see that NETBIOS is active. Check for a redirector. │
;╘═══════════════════════════════════════════════════════════════════════════╛
CALL CHECKDOS ;DOS better be 3.1 or greater
CALL CHKNETB ;See if NETBIOS is in here
JNC NBTHERE
PUSH OFFSET CS:NASTYGRAM ;Whoa! No NETBIOS!
CALL FAILPROG ;Die.
NBTHERE:
MOV AH,0
INT 2Ah ;Check for redirector
MOV REDIRACTIVE,AH
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Look for TIMESEND.DAT file. Verify filesize. Extract NETBIOS names. │
;╘═══════════════════════════════════════════════════════════════════════════╛
MOV AH,3Dh ;Open file
XOR AL,AL
MOV DX,OFFSET FILENAME
INT 21h
JNC FILEISOPEN ;Good open, jump
MOV AH,9 ;Bad open
MOV DX,OFFSET ASSUMPTION ;Display warning msg
INT 21h
JMP ADDNBNAME ;...and proceed.
FILEISOPEN:
MOV HANDLE,AX
MOV BX,AX
MOV AH,42h ;Seek to end of file
MOV AL,02h
XOR CX,CX
XOR DX,DX
INT 21h
CMP AX,32
JB SHORTFILE
CMP AX,35
JA LONGFILE
MOV BX,HANDLE
MOV AH,42h ;Seek to start of file
MOV AL,00h
XOR CX,CX
XOR DX,DX
INT 21h
MOV BX,HANDLE
MOV AH,3Fh ;Read from file
MOV CX,32
MOV DX,OFFSET MYNAME
INT 21h
JNC CLOSEFILE
PUSH OFFSET CS:READFAILED
CALL FAILPROG
SHORTFILE:
PUSH OFFSET CS:FILESHORT
CALL FAILPROG
LONGFILE:
PUSH OFFSET CS:FILELONG
CALL FAILPROG
CLOSEFILE:
MOV BX,HANDLE
MOV AH,3Eh ;Close file
INT 21h
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Add our name to the NETBIOS name table. │
;╘═══════════════════════════════════════════════════════════════════════════╛
ADDNBNAME:
CALL CLEARNCB ;Zero the NCB first
MOV AL,ADDNAME ;Fill in NCB fields
MOV CB.NCB_COMMAND,AL
PUSH CS
POP ES
MOV DI,OFFSET CB.NCB_NAME
MOV SI,OFFSET MYNAME
MOV CX,16
CLD
REP MOVSB
MOV BX,OFFSET CB
CALL CALLNB ;Call NETBIOS
MOV AL,CB.NCB_RETCODE
OR AL,AL ;Check status
JZ ADDWASOK
PUSH OFFSET CS:ADDFAILED ;Whoa! It didn't work.
CALL FAILPROG ;Die.
ADDWASOK:
MOV AL,CB.NCB_NUM ;Grab "name number" returned
MOV NAMENUM,AL ; and save it for use later.
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Get the current address of Int 1C and save (it's the timer interrupt) │
;╘═══════════════════════════════════════════════════════════════════════════╛
MOV AH,35h ;Get Int vector
MOV AL,1Ch ;For this Int
INT 21h ;Result in ES:BX
ASSUME ES:NOTHING
MOV WORD PTR PREVGUY[0],BX ;offset
MOV WORD PTR PREVGUY[2],ES ;segment
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Free our environment segment to save a little space. │
;╘═══════════════════════════════════════════════════════════════════════════╛
PUSH DS
MOV AH,62h ;Get PSP address
INT 21h ;
MOV DS,BX
MOV ES,DS:2Ch ;ES<-Env Seg Addr
MOV AH,49h ;Free memory alloc
INT 21h ;
POP DS
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Plug ourselves into DOS Timer Interrupt (Interrupt 1C). │
;╘═══════════════════════════════════════════════════════════════════════════╛
PUSH DS
PUSH CS
POP DS
MOV DX,OFFSET INT_1C ;INT_1C is ISR entry
MOV AH,25h ;Set Interrupt vector
MOV AL,1Ch ; 1Ch.
INT 21h ;
POP DS
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ Terminate and stay resident. │
;╘═══════════════════════════════════════════════════════════════════════════╛
MOV AX,3100H
MOV DX,(OFFSET LASTBYTE - OFFSET CSEG + 15) SHR 4
INT 21H
INITIALIZE ENDP
HANDLE DW 0
FILENAME DB "\TIMESEND.DAT",00h
NASTYGRAM DB "NETBIOS is NOT active on this system",0Ah,0Dh,'$'
ADDFAILED DB "NETBIOS Add Name failed",0Ah,0Dh,'$'
ASSUMPTION DB "Assuming TIMESERVER sends to TIMECLIENT",0Ah,0Dh,'$'
FILESHORT DB "TIMESEND.DAT file too small to be valid",0Ah,0Dh,'$'
FILELONG DB "TIMESEND.DAT fill too big to be valid",0Ah,0Dh,'$'
READFAILED DB "Error reading TIMESEND.DAT",0Ah,0Dh,'$'
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ FAILPROG --- Display string (terminated with "$") on console, then │
;│ exit the program with nonzero condition code. │
;╘═══════════════════════════════════════════════════════════════════════════╛
FAILPROG PROC NEAR
PUSH SP
POP BX
MOV DX,WORD PTR [BX+2] ;Get offset of string
PUSH CS ;Assume offset w/in this code
POP DS
MOV AH,09h ;Display String function
INT 21h ; of DOS
MOV AH,4Ch ;Terminate a Process func
MOV AL,01h ; of DOS
INT 21h ;
INT 20h ;Just to be safe....
FAILPROG ENDP
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ CHECKDOS --- Get the DOS version. Bomb if < DOS 3.10. │
;╘═══════════════════════════════════════════════════════════════════════════╛
CHECKDOS PROC NEAR
PUSH BP ;Save register(s)
MOV BP,SP
PUSH CX
PUSH BX
PUSH AX
MOV AH,30h ;Get DOS Version
INT 21h
MOV CS:VER,AX ;Save results
MOV CS:DOSMAJOR,AL
MOV CS:DOSMINOR,AH
CMP AL,3 ;Check major level
JL VERCHOKE ;<3, VERCHOKE
JNE VEROK ;>3, VEROK
CMP AH,1 ;Check minor level for 3.x
JGE VEROK ;VEROK if 3.1 or better
VERCHOKE:
PUSH OFFSET CS:VERMSG ;Push offset of nastygram
CALL FAILPROG ;And kiss off....
VEROK:
POP AX ;Restore registers
POP BX
POP CX
MOV SP,BP ;Restore stack
POP BP
RET ;Return to caller
CHECKDOS ENDP
VERMSG DB "DOS Version MUST be 3.1 or greater$"
;╔═══════════════════════════════════════════════════════════════════════════╗
;║ Check For NETBIOS Installed in System ║
;║ Return with CARRY SET if NOT installed ║
;╚═══════════════════════════════════════════════════════════════════════════╝
CHKNETB PROC NEAR
MOV AH,35h ;Who's plugged into INT 5C?
MOV AL,5Ch
INT 21h
MOV AX,ES
CMP AX,0000h
JE NOTKOSHER
CMP AX,0F000h
JE NOTKOSHER
ITSPLUGGED:
PUSH CS
POP ES
MOV DI,OFFSET FUNKYNCB ;Zero the NCB
MOV CX,NCB_SIZE
XOR AL,AL
CLD
REP STOSB
MOV BX,OFFSET FUNKYNCB
MOV AL,0FFh
MOV FUNKYNCB.NCB_COMMAND,AL
MOV AL,00h
INT 5Ch ;Check it.
MOV AL,FUNKYNCB.NCB_RETCODE
CMP AL,03h ;Zero ?
JNE NOTKOSHER ;Yes, so not installed.
CLC
RET
NOTKOSHER:
STC
RET
FUNKYNCB NCB <> ;NCB with FUNKY command
; to test things out
CHKNETB ENDP
CSEG ENDS
END ENTPT
;╔═══════════════════════════════════════════════════════════════════════════╗
;║ End of Program --- TIMESEND ║
;╚═══════════════════════════════════════════════════════════════════════════╝